#!usr/bin/env python3
import logging
import utils.strUtil
from datetime import datetime
from flask import Flask,request,current_app,render_template,redirect,url_for,session,flash
from flask_bootstrap import Bootstrap
from flask_moment import Moment
from flask_wtf import FlaskForm
from flask_wtf.csrf import CsrfProtect
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
from flask_sqlalchemy import SQLAlchemy
from dbModel import db
from flask_mail import Mail,Message
from threading import Thread
from flask_script import Manager
from flask_migrate import Migrate,MigrateCommand

#http://127.0.0.1:5000/

#设置日志
logging.basicConfig(level=logging.DEBUG,  
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',  
                    datefmt='%a, %d %b %Y %H:%M:%S',  
                    filename='weblogs.log',  
                    filemode='w')
strUtil = utils.strUtil

app = Flask(__name__) #把__name__传递初始化,主要是让flask知道根目录
Bootstrap(app)
moment = Moment(app) #momentjs的flask扩展
CsrfProtect(app) #Csrf攻击保护 
manager = Manager(app) #flask_script扩展命令行实例化,管理脚步

migrate = Migrate(app,db) #创建数据库迁移
manager.add_command("db",MigrateCommand) #用flask_script创建数据库迁移命令 
'''
数据库迁移命令说明：
1.在维护数据库迁移之前，要使用init 子命令创建迁移仓库：
# python app.py db init
2. migrate 子命令用来自动创建迁移脚本：
(upgrade() 函数把迁移中的改动应用到数据库中，downgrade() 函数则将改动
删除。Alembic 具有添加和删除改动的能力，因此数据库可重设到修改历史的任意一点)
我们可以使用revision 命令手动创建Alembic 迁移，也可使用migrate 命令自动创建。
手
python hello.py db migrate -m "initial migration" #这个是自动创建迁移脚步,只需执行一次(相当于执行db.create_all())

3.更新数据库 (做添加或者删除字段等改变数据表结构的操作后 可以执行该命令自动更新数据库,把新的结构和数据都一起迁移)
python hello.py db upgrade 
'''
app.config.from_object("config.DevelopmentConfig") #初始化配置
mail = Mail(app)
db.init_app(app) #先注册当前的app
db.app = app    #再设置上下文的app为当前的app,这部不能少不然会报错
#db.drop_all()  #先删除旧的 当前的处理方式,实际项目不会这样处理
db.create_all() #再创建,保证每次都是最新的

#自定义一个表单
class NameForm(FlaskForm):
    # 每个字段都有validators参数指定验证函数列表,Required函数表示验证输入内容不能为空 
    name = StringField('请输入用户名:',id='formIpt',validators=[DataRequired('用户名不能为空')]) 
    submit = SubmitField()

#设置日志
@app.route("/",methods=['GET','POST'])
def index():       
    form = NameForm()
    isSubmit = form.validate_on_submit() #检查当前是否是提交表单     
    if isSubmit:        
        session['name'] = form.name.data #服务端的用户数据储存在session中
        form.name.data = ""        
        return redirect(url_for('index'))
    else:
        if request.method=='POST':
            logging.info("post="+str(form.errors))
            flash('请输入名字')
    name = session.get('name') #从session中获取    
    
    '''
    if name: # 623097864  1003889336
        send_mail(['623097864@qq.com'],'测试发送邮件的代码','ask',False,name=name)
    '''

    return render_template("index.html",
    name=name,title="HelloCode",form=form,
    current_time=datetime.utcnow()) #渲染模板

#动态路由;注意设置动态路由的格式
@app.route("/user/<name>")
def user(name):    
    return render_template("sub/user.html",name=name)
 
@app.route("/about")
def about():    
    return render_template("sub/about.html")

@app.route("/product")
def product():
    return render_template("sub/product.html",imgs=['p1.png','p2.png','p3.png'])

@app.route("/product/<string:img>") #指定数据类型的路由
def product_detail(img):
    return render_template("sub/product_detail.html",img=img)

@app.errorhandler(404) #自定义404错误页面
def page_not_found(e):
     return render_template("error/404.html"),404

@app.errorhandler(500) #自定义500错误页面
def unknow_err(e):
     return render_template("error/500.html"),500

@app.route("/data/<param>")
def reciveClient(param):
    logging.info(param)

#异步发送邮件
def send_async_mail(app,msg):
    with app.app_context():
        mail.send(msg)

'''
发送邮件
@param toList 接收列表
@param title  邮件标题
@param tplName 邮件目标名(txt和html文件)
@param kw      目标的参数
'''
def send_mail(toList,title,tplName,isAsync=False,**kw):
    msg = Message(title,sender='623097864@qq.com',recipients=toList)
    msg.body = render_template('mail/'+tplName+'.txt',**kw)
    msg.html = render_template('mail/'+tplName+'.html',**kw)
    if isAsync:
        thr = Thread(target=send_async_mail,args=[app,msg])
        thr.start()
        return thr
    else:
        mail.send(msg)
        return None
    


    
